/*************************************************************************************
*Copyright (c) 2011, Intel Mobile Communications GmbH. 
*All rights reserved.
*
*Redistribution and use in source and binary forms, with or without
*modification, are permitted provided that the following conditions are met:
*    * Redistributions of source code must retain the above copyright
*      notice, this list of conditions and the following disclaimer.
*    * Redistributions in binary form must reproduce the above copyright
*      notice, this list of conditions and the following disclaimer in the
*      documentation and/or other materials provided with the distribution.
*    * Neither the name of the <organization> nor the
*      names of its contributors may be used to endorse or promote products
*      derived from this software without specific prior written permission.
*
*THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
*ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
*WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
*DISCLAIMED. IN NO EVENT SHALL INTEL MOBILE COMMUNICATIONS GMBH. BE LIABLE FOR ANY
*DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
*(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
*LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
*ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
*(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*************************************************************************************/



#include "cef_routes.h"
using namespace std;
cef_src_route::cef_src_route()
{
	source_id=0;
	destination_id=0;
	switch_output_port_ids=NULL;
	weight=0;
}
cef_src_route::cef_src_route(unsigned s,unsigned d,std::vector<unsigned>* sw, double w):source_id(s),destination_id(d)
{
	switch_output_port_ids=sw;
	weight=w;
}
cef_src_route::~cef_src_route()
{
	if(switch_output_port_ids) delete switch_output_port_ids;
}

void cef_src_route::setSrcID(unsigned s)
{
	source_id=s;
}
void cef_src_route::setDstID(unsigned d)
{
	destination_id;	
}
void cef_src_route::setSOPI(std::vector<unsigned>* sw)
{
	switch_output_port_ids=sw;
}
void cef_src_route::setWeight(double w)
{
	weight=w;
}
	//Getters
unsigned cef_src_route::getSrcID()
{
	return source_id;
}
unsigned cef_src_route::getDstID()
{
	return destination_id;
}

std::vector<unsigned>* cef_src_route::getSOPI()
{
	return switch_output_port_ids;
}
double cef_src_route::getWeight()
{
	return weight;
}
#ifdef _DEBUG
void cef_src_route::print()
{
	cout<<"CEF Route\nBEGIN\n";
	cout<<"Source ID: "<<source_id<<" Destination ID: "<<destination_id<<" Weight: "<<weight<<endl;
	if(switch_output_port_ids)
	{
		cout<<"Switch OutPorts IDs: ";
		for(unsigned i=0;i<switch_output_port_ids->size();i++)
		{
			cout<<(*switch_output_port_ids)[i]<<" ";
		}
		cout<<endl;
	}
	cout<<"END\n";
}
#endif
cef_routes_switch::cef_routes_switch()
{
	id=0;
	outport=0;
	linknum=0;
}
cef_routes_switch::cef_routes_switch(unsigned i, unsigned o, unsigned l)
{
	id=i;
	outport=o;
	linknum=l;
}
cef_routes_switch::~cef_routes_switch()
{
}
//Setters
void cef_routes_switch::setID(unsigned i)
{
	id=i;
}
void cef_routes_switch::setOutPort(unsigned o)
{
	outport=o;
}
void cef_routes_switch::setLinkNum(unsigned l)
{
	linknum=l;
}
//Getters
unsigned cef_routes_switch::getID()
{
	return id;
}
unsigned cef_routes_switch::getOutPort()
{
	return outport;
}
unsigned cef_routes_switch::LinkNum()
{
	return linknum;
}
#ifdef _DEBUG
void cef_routes_switch::print()
{
	cout<<"CEF Route Switch\nBEGIN\n";
	cout<<"ID: "<<id<<" OutPort: "<<outport<<" LinkNum: "<<linknum<<endl;
	cout<<"END\n";
}
#endif
cef_sourcerouting::cef_sourcerouting()
{
	routes=NULL;
}
cef_sourcerouting::cef_sourcerouting(std::vector<cef_src_route*>* v)
{
	routes=v;
}
cef_sourcerouting::~cef_sourcerouting()
{
	if(routes)
	{
		for(unsigned i=0;i<routes->size();i++)
		{
			delete (*routes)[i];
		}
		delete routes;
	}
}
//Setters
void cef_sourcerouting::setRoutes(std::vector<cef_src_route*>* s)
{
	routes=s;
}
std::vector<cef_src_route*>* cef_sourcerouting::getRoutes()
{
	return routes;
}
#ifdef _DEBUG
void cef_sourcerouting::print()
{
	cout<<"CEF Source Routing\nBEGIN\n";
	if(routes)
	{
		for(unsigned i=0;i<routes->size();i++)
		{
			(*routes)[i]->print();
		}
	}
	cout<<"END\n";
}
#endif
cef_routing_table::cef_routing_table()
{
	switch_id=0;
	destination_id=0;
	output_ports=NULL;
	input_port_id=0;
}
cef_routing_table::cef_routing_table(unsigned s, unsigned d,unsigned i, std::vector<std::pair<unsigned,double>* >* o)
{
	switch_id=s;
	destination_id=d;
	output_ports=o;
	input_port_id=i;
}
cef_routing_table::~cef_routing_table()
{
	if(output_ports)
	{
		for(unsigned i=0;i<output_ports->size();i++)
		{
			delete (*output_ports)[i];
		}
		delete output_ports;
	}
}
	//Setters
void cef_routing_table::setSwID(unsigned s)
{
	switch_id=s;
}
void cef_routing_table::setDstID(unsigned d)
{
	destination_id=d;
}
void cef_routing_table::setInpID(unsigned i)
{
	input_port_id=i;
}
void cef_routing_table::setOutPorts(std::vector<std::pair<unsigned, double>* >* o)
{
	output_ports=o;	
}
//Getters
unsigned cef_routing_table::getSwID()
{
	return switch_id;
}
unsigned cef_routing_table::getDstID()
{
	return destination_id;
}
unsigned cef_routing_table::getInpID()
{
	return input_port_id;
}
std::vector<std::pair<unsigned,double>* >* cef_routing_table::getOutPorts()
{
	return output_ports;
}
#ifdef _DEBUG
void cef_routing_table::print()
{
	cout<<"CEF Routing Table\nBEGIN\n";
	cout<<"Switch ID: "<<switch_id<<" Input Port ID: "<<input_port_id<<" Destination ID: "<<destination_id<<endl;
	if(output_ports)
	{
		cout<<"Output Ports:\n";
		for(unsigned i=0;i<output_ports->size();i++)
		{
			cout<<"ID: "<<(*output_ports)[i]->first<<" Weight: "<<(*output_ports)[i]->second<<endl;
		}
	}
	cout<<"END\n";
}
#endif
cef_distributedrouting::cef_distributedrouting()
{
	tables=NULL;	
}
cef_distributedrouting::cef_distributedrouting(std::vector<cef_routing_table*>* t)
{
	tables=t;
}
cef_distributedrouting::~cef_distributedrouting()
{
	if(tables)
	{
		for(unsigned i=0;i<tables->size();i++)
		{
			delete (*tables)[i];
		}
		delete tables;
	}	
}
	//Setters
void cef_distributedrouting::setTables(std::vector<cef_routing_table*>* t)
{
	tables=t;
}
	//Getters
std::vector<cef_routing_table*>* cef_distributedrouting::getTables()
{
	return tables;
}
#ifdef _DEBUG
void cef_distributedrouting::print()
{
	cout<<"CEF Distributed Routing\nBEGIN\n";
	if(tables)
	{
		for(unsigned i=0;i<tables->size();i++)
		{
			(*tables)[i]->print();
		}
	}
	cout<<"END\n";
}
#endif



cef_lbdr_fork::cef_lbdr_fork()
{
	input_port_id=0;		
	fork_ports=NULL;
}
cef_lbdr_fork::cef_lbdr_fork(unsigned i,std::vector<unsigned>* f)
{
	input_port_id=i;
	fork_ports=f;	
}
cef_lbdr_fork::~cef_lbdr_fork()
{
	if(fork_ports) delete fork_ports;
}
	//Setters
void cef_lbdr_fork::setInpID(unsigned x)
{
	input_port_id=x;
}
void cef_lbdr_fork::setForkPorts(std::vector<unsigned>* f)
{
	fork_ports=f;	
}
	//Getters
unsigned cef_lbdr_fork::getInpID()
{
	return input_port_id;	
}
vector<unsigned>* cef_lbdr_fork::getForkPorts()
{
	return fork_ports;
}
#ifdef _DEBUG
void cef_lbdr_fork::print()
{
	cout<<"CEF LBDR Fork\nBEGIN\n";
	cout<<"Input Port ID: "<<input_port_id<<endl;
	if(fork_ports)
	{
		cout<<"Fork Ports: ";
		for(unsigned i=0;i<fork_ports->size();i++)
		{
			cout<<(*fork_ports)[i]<<" ";
		}
		cout<<endl;
	}
	cout<<"END\n";
}
#endif
	


cef_lbdr_entry::cef_lbdr_entry()
{
	switch_id=0;
	routing_bits=0;
	connectivity_bits=0;
}
cef_lbdr_entry::cef_lbdr_entry(unsigned s, unsigned long long r, unsigned long long c, vector<pair<unsigned,unsigned>*>* d , vector<cef_lbdr_fork*>* f)
{
	switch_id=s;	
	routing_bits=r;
	connectivity_bits=c;
	lbdr_deroutes=d;
	lbdr_forks=f;
}
cef_lbdr_entry::~cef_lbdr_entry()
{
	if(lbdr_deroutes)
	{
		for(unsigned i=0;i<lbdr_deroutes->size();i++)
		{
			delete (*lbdr_deroutes)[i];	
		}
		delete lbdr_deroutes;
	}
	if(lbdr_forks)
	{
		for(unsigned i=0;i<lbdr_forks->size();i++)
		{
			delete (*lbdr_forks)[i];	
		}
		delete lbdr_forks;

	}
}
	//Setters
void cef_lbdr_entry::setSwID(unsigned s)
{
	switch_id=s;
}
void cef_lbdr_entry::setRoutingBits(unsigned long long r)
{
	routing_bits=r;	
}
void cef_lbdr_entry::setConnectBits(unsigned long long c)
{
	connectivity_bits=c;
}
void cef_lbdr_entry::setDeroutes(vector<pair<unsigned,unsigned>*>* d)
{
	lbdr_deroutes=d;
}
void cef_lbdr_entry::setForks(vector<cef_lbdr_fork*>*f)
{
	lbdr_forks=f;
}
	//Getters
unsigned cef_lbdr_entry::getSwID()
{
	return switch_id;
}
unsigned long long cef_lbdr_entry::getRoutingBits()
{
	return routing_bits;
}
unsigned long long cef_lbdr_entry::getConnectBits()
{
	return connectivity_bits;
}
vector<pair<unsigned,unsigned>*>* cef_lbdr_entry::getDeroutes()
{
	return lbdr_deroutes;
}
vector<cef_lbdr_fork*>* cef_lbdr_entry::getForks()
{
	return lbdr_forks;
}
#ifdef _DEBUG
void cef_lbdr_entry::print()
{
	cout<<"CEF LBDR Entry\nBEGIN\n";
	cout<<" Switch ID: "<<switch_id<<" Routing Bits: "<<routing_bits<<" Connectivity Bits: "<<connectivity_bits<<endl;
	if(lbdr_deroutes)
	{
		cout<<"Deroutes: ";
		for(unsigned i=0;i<lbdr_deroutes->size();i++)
		{
			cout<<"("<<(*lbdr_deroutes)[i]->first<<","<<(*lbdr_deroutes)[i]->second<<") ";
		}
		cout<<endl;
	}	
	if(lbdr_forks)
	{
		cout<<"Forks: ";	
		for(unsigned i=0;i<lbdr_forks->size();i++)
		{
			(*lbdr_forks)[i]->print();
		}
	}
	cout<<"END\n";	
}
#endif

cef_lbdr::cef_lbdr()
{
	entries=NULL;
}
cef_lbdr::cef_lbdr(std::vector<cef_lbdr_entry*>* e)
{
	entries=e;
}
cef_lbdr::~cef_lbdr()
{
	if(entries)
	{
		for(unsigned i=0;i<entries->size();i++)
		{
			delete (*entries)[i];
		}
		delete entries;
	}
}
	//Setters
void cef_lbdr::setEntries(std::vector<cef_lbdr_entry*>* e)
{
	entries=e;
}
	//Getters
std::vector<cef_lbdr_entry*>* cef_lbdr::getEntries()
{
	return entries;
}
#ifdef _DEBUG
void cef_lbdr::print()
{
	cout<<"CEF LBDR\nBEGIN\n";
	if(entries)	
	{
		for(unsigned i=0;i<entries->size();i++)
		{
			(*entries)[i]->print();
		}
	}
	cout<<"END\n";
}
#endif
cef_fdor::cef_fdor()
{
	fdor_entries=NULL;
}
cef_fdor::cef_fdor(std::vector<std::pair<unsigned , unsigned long long>* >* e)
{
	fdor_entries=e;
}

cef_fdor::~cef_fdor()
{
	if(fdor_entries)
	{
		for(unsigned i=0;i<fdor_entries->size();i++)
		{	
			delete (*fdor_entries)[i];
		}
		delete fdor_entries;
	}
}
//Setters
void cef_fdor::setEntries(std::vector<std::pair<unsigned , unsigned long long>* >* e)
{
	fdor_entries=e;
}
//Getters
std::vector<std::pair<unsigned , unsigned long long>* >* cef_fdor::getEntries()
{
	return fdor_entries;
}
#ifdef _DEBUG
void cef_fdor::print()
{
	cout<<"CEF FDOR\nBEGIN\n";
	if(fdor_entries)
	{
		for(unsigned i=0;i<fdor_entries->size();i++)
		{
			cout<<"Switch ID: "<<(*fdor_entries)[i]->first<<" FDOR Bit: "<<(*fdor_entries)[i]->second<<endl;
		}
	}
	cout<<"END\n";
}
#endif
	
cef_virtual_network::cef_virtual_network()
{
	id=0;
	vcs=NULL;
}
cef_virtual_network::cef_virtual_network(unsigned i ,std::vector<unsigned>* v)
{
	id=i;	
	v=vcs;
}

cef_virtual_network::~cef_virtual_network()
{
	if(vcs)delete vcs;
}
	//Setters
void cef_virtual_network::setID(unsigned i)
{
	id=i;
}
void cef_virtual_network::setVCs(std::vector<unsigned>* v)
{
	vcs=v;
}
	//Getters
unsigned cef_virtual_network::getID()
{
	return id;
}
std::vector<unsigned>* cef_virtual_network::getVCs()
{
	return vcs;
}
#ifdef _DEBUG
void cef_virtual_network::print()
{
	cout<<"CEF Virtual Network\nBEGIN\n";	
	cout<<"ID: "<<id<<endl;
	if(vcs)
	{
		cout<<"Virtual Channels: ";
		for(unsigned i=0;i<vcs->size();i++)	
		{
			cout<<(*vcs)[i]<<" ";
		}
		cout<<endl;
	}
	cout<<"END\n";
}
#endif
cef_routes::cef_routes()
{
	routing_policy="";
	sourcerouting=NULL;
	distributedrouting=NULL;
	lbdr=NULL;
	fdor=NULL;
	virtual_networks=NULL;
}
cef_routes::cef_routes(string r,cef_sourcerouting* s,cef_distributedrouting* d, cef_lbdr* l, cef_fdor* f, std::vector<cef_virtual_network* >* v)
{
	routing_policy=r;	
	sourcerouting=s;
	distributedrouting=d;
	lbdr=l;
	fdor=f;
	virtual_networks=v;
}
cef_routes::~cef_routes()
{
	if(sourcerouting) delete sourcerouting;
	if(distributedrouting) delete distributedrouting;
	if(lbdr) delete lbdr;
	if(fdor) delete fdor;
	if(virtual_networks)
	{
		for(unsigned i=0;i<virtual_networks->size();i++)	
		{
			delete (*virtual_networks)[i];
		}
		delete virtual_networks;
	}
}
//Setters
void cef_routes::setRoutingPolicy(string r)
{
	routing_policy=r;
}
void cef_routes::setSourceRouting(cef_sourcerouting* s)
{
	sourcerouting=s;
}
void cef_routes::setDistributedRouting(cef_distributedrouting* d)
{
	distributedrouting=d;
}
void cef_routes::setLBDR(cef_lbdr* l)
{
	lbdr=l;
}
void cef_routes::setFDOR(cef_fdor* f)
{
	fdor=f;
}
void cef_routes::setVNs(vector<cef_virtual_network*>* v)
{
	virtual_networks=v;
}
//Getters
string cef_routes::getRoutingPolicy()
{
	return routing_policy;
}
cef_sourcerouting* cef_routes::getSourceRouting()
{
	return sourcerouting;
}
cef_distributedrouting* cef_routes::getDistributedRouting()
{
	return distributedrouting;
}

cef_lbdr* cef_routes::getLBDR()
{
	return lbdr;
}
cef_fdor* cef_routes::getFDOR()
{
	return fdor;
}
std::vector<cef_virtual_network*>* cef_routes::getVNs()
{
	return virtual_networks;
}

#ifdef _DEBUG
void cef_routes::print()
{
	cout<<"CEF Route\nBEGIN\n";
	if(sourcerouting) sourcerouting->print();
	if(distributedrouting) distributedrouting->print();
	if(lbdr) lbdr->print();
	if(fdor) fdor->print();
	if(virtual_networks)
	{
		cout<<"Virtual Networks : ";
		for(unsigned i=0;i<virtual_networks->size();i++)
		{
			(*virtual_networks)[i]->print();	
		}
		cout<<endl;
	}
	cout<<"END\n";
}
#endif
